﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using DataModels.Models;
using GenericTools;
using ReportingManagement.Models;

namespace ReportingManagement.Components
{
    /// <summary>
    /// Interaction logic for ReportMergingView.xaml
    /// </summary>
    public partial class ReportMergingView : UserControl
    {
        private ObservableCollection<DefinitionComponent> indicators;
        private ObservableCollection<DefinitionComponent> operators;
        private ObservableCollection<DefinitionComponent> functions;

        private ObservableCollection<IndicatorDefinition> indicatorDefinitions;

        public ReportMergingView()
        {
            InitializeComponent(); 
            indicatorDefinitions = new ObservableCollection<IndicatorDefinition>();
            
            CreateOperatorList();
            cboOperator.ItemsSource = operators;
        }

        public void Reload(int mergingId)
        {
            gboFormula.Visibility = Visibility.Collapsed;
            ReportMerge reportMerge = Utilities.GetReportMergeDetails(mergingId);
            if (reportMerge != null)
            {
                txtMergingName.Text = reportMerge.Name;
                txtMergingDescription.Text = reportMerge.Description;
                cboDestinationReport.SelectedValue = reportMerge.MergingReports[0].DestinationReportId;

                lstSourceReports.SelectedItems.Clear();
                foreach (var r in lstSourceReports.Items)
                {
                    DataRowView row = r as DataRowView;
                    int reportId = int.Parse(row["RepID"].ToString());
                    foreach (var i in reportMerge.MergingReports)
                    {
                        if (i.SourceReportId == reportId)
                        {
                            lstSourceReports.SelectedItems.Add(r);
                            lstSourceReports_SelectionChanged(null, null);
                            break;
                        }
                    }
                }

                #region Loading indicator definition
                for (int i = 0; i < gridIndicatorDefinitions.Items.Count; i++)
                {
                    IndicatorDefinition d = gridIndicatorDefinitions.Items[i] as IndicatorDefinition;
                    gridIndicatorDefinitions.SelectedItem = d;

                    ReportDataMerging reportDataMerging = reportMerge.ReportDataMerging[i];
                    var sourceDefinition = reportDataMerging.SourceIndicator;

                    string[] components = sourceDefinition.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
                    for (int j = 0; j < components.Length; j++)
                    {
                        string component = components[j];
                        if ((j % 2) == 0)
                        {
                            string[] parts = component.Split(new string[] { "." }, StringSplitOptions.RemoveEmptyEntries);
                            string sSourceReportId = parts[0].Replace("{", string.Empty).Replace("}", string.Empty);

                            // Check to see if the component is the fixed number.
                            // Fixed are saved like this [2] where 2 is the target number.
                            if (sSourceReportId.StartsWith("["))
                            {
                                string sNumber = sSourceReportId.Replace("[", string.Empty).Replace("]", string.Empty);
                                int number;
                                bool converted = int.TryParse(sNumber, out number);
                                if (!converted) number = 0;
                                txtNumber.Text = number.ToString();
                                btnAddNumber_Click(null, null);
                            }
                            else
                            {
                                // Here we are dealing with report indicators and how to populate
                                // them into the UI.

                                int sourceReportId = int.Parse(sSourceReportId);
                                string shortCode = parts[1];
                                //Find from indicators list the one that matches the above criteria
                                foreach (var indicator in cboIndicator.Items)
                                {
                                    DataRowView r = indicator as DataRowView;
                                    int id = int.Parse(r["RepID"].ToString());
                                    if (id == sourceReportId)
                                    {
                                        string code = r["ShortCode"].ToString();
                                        if (code == shortCode)
                                        {
                                            cboIndicator.SelectedItem = indicator;
                                            btnAddIndicator_Click(null, null);
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                        else
                        {
                            foreach (var p in cboOperator.Items)
                            {
                                DefinitionComponent c = p as DefinitionComponent;
                                if (c.Name == component)
                                {
                                    cboOperator.SelectedItem = p;
                                    btnAddOperator_Click(null, null);
                                    break;
                                }
                            }
                        }
                    }
                }
                #endregion
            }
        }

        private void CreateOperatorList()
        {
            if (operators != null) operators.Clear();
            operators = new ObservableCollection<DefinitionComponent>
            {
                new DefinitionComponent { Name = "+" },
                new DefinitionComponent { Name = "-" }
            };
        }

        private void cboDestinationReport_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var item = cboDestinationReport.SelectedItem as DataRowView;
            if (item != null)
            {
                int id = int.Parse(item["RepID"].ToString());
                string name = item["ReportName"].ToString();

                DataTable reportDetail = GetReportDetails(id);
                indicatorDefinitions.Clear();
                foreach (DataRow r in reportDetail.Rows)
                {
                    string shortCode = r["ShortCode"].ToString();
                    string description = r["DataDescription"].ToString();
                    var indicatorDefinition = new IndicatorDefinition
                    {
                        Name = shortCode,
                        Description = description
                    };
                    indicatorDefinitions.Add(indicatorDefinition);
                }

                gridIndicatorDefinitions.ItemsSource = indicatorDefinitions;
                ReloadReportIndicators();
            }
        }

        private void lstSourceReports_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            ReloadReportIndicators();
        }

        private void ReloadReportIndicators()
        {
            DataTable dataTable = null;
            bool containerCreated = false;

            if (cboIndicator.ItemsSource != null)
            {
                var dataView = cboIndicator.ItemsSource as DataView;
                if (dataView != null)
                {
                    dataTable = dataView.Table;
                    if (dataTable != null)
                    {
                        containerCreated = true;
                        dataTable.Rows.Clear();
                    }
                }
            }

            foreach (var i in lstSourceReports.SelectedItems)
            {
                DataRowView r = i as DataRowView;
                if (r != null)
                {
                    int id = int.Parse(r["RepID"].ToString());
                    if (!containerCreated)
                    {
                        dataTable = GetReportDetails(id);
                        containerCreated = true;
                    }
                    else
                    {
                        var temp = GetReportDetails(id);
                        dataTable.Merge(temp);
                    }
                }
            }

            if (dataTable != null)
            {
                cboIndicator.DisplayMemberPath = "DataDescription";
                cboIndicator.ItemsSource = dataTable.DefaultView;
            }
        }

        Dictionary<int, DataTable> reportDetails = new Dictionary<int, DataTable>();
        private DataTable GetReportDetails(int reportId)
        {
            DataTable dataTable = null;
            if (reportDetails.ContainsKey(reportId)) dataTable = reportDetails[reportId];
            else dataTable = Utilities.GetReportDataLocations(reportId);
            reportDetails[reportId] = dataTable;

            // Adding reportId column for easy management
            // The dataTable object may be modified in this class so we return a fresh copy
            dataTable = dataTable.Copy();
            var column = new DataColumn("RepID", Type.GetType("System.Int32"));
            dataTable.Columns.Add(column);
            foreach (DataRow r in dataTable.Rows) r["RepID"] = reportId;            
            return dataTable;
        }

        private void btnAddIndicator_Click(object sender, RoutedEventArgs e)
        {
            var indicatorDefinition = gridIndicatorDefinitions.SelectedItem as IndicatorDefinition;
            if (indicatorDefinition != null)
            {
                if (cboIndicator.SelectedItem != null)
                {
                    DataRowView row = cboIndicator.SelectedItem as DataRowView;
                    if (row != null)
                    {
                        string shortCode = row["ShortCode"].ToString();
                        var component = new DefinitionComponent
                        {
                            Name = shortCode,
                            Tag = row
                        };
                        
                        indicatorDefinition.AddComponent(component);
                    }
                }
            }            
        }

        private void btnRemoveIndicator_Click(object sender, RoutedEventArgs e)
        {
            var indicatorDefinition = gridIndicatorDefinitions.SelectedItem as IndicatorDefinition;
            if (indicatorDefinition != null)
            {
                if (string.IsNullOrWhiteSpace(indicatorDefinition.Definition)) ;
                else indicatorDefinition.RemoveComponent(); 
            }
        }

        private void btnRemoveOperator_Click(object sender, RoutedEventArgs e)
        {
            var indicatorDefinition = gridIndicatorDefinitions.SelectedItem as IndicatorDefinition;
            if (indicatorDefinition != null)
            {
                if (string.IsNullOrWhiteSpace(indicatorDefinition.Definition)) ;
                else indicatorDefinition.RemoveComponent();
            }
        }

        private void btnAddOperator_Click(object sender, RoutedEventArgs e)
        {
            var indicatorDefinition = gridIndicatorDefinitions.SelectedItem as IndicatorDefinition;
            if (indicatorDefinition != null)
            {
                if (cboOperator.SelectedItem != null)
                {
                    var component = cboOperator.SelectedItem as DefinitionComponent;
                    if (component != null) indicatorDefinition.AddComponent(component);
                }
            }     
        }

        public int DestinationReportId
        {
            get
            {
                int reportId = int.Parse(cboDestinationReport.SelectedValue.ToString());
                return reportId;
            }
        }

        public List<int> SourceReportIds
        {
            get
            {
                var sourceReports = new List<int>();
                foreach (var r in lstSourceReports.SelectedItems)
                {
                    DataRowView row = (DataRowView)r;
                    int reportId = int.Parse(row["RepID"].ToString());
                    sourceReports.Add(reportId);
                }
                return sourceReports;
            }
        }

        public List<string> IndicatorDefinitions
        {
            get
            {
                var indicatorDefinitions = new List<string>();
                foreach (var i in gridIndicatorDefinitions.Items)
                {
                    var definition = (IndicatorDefinition)i;
                    string definitionText = definition.DefinitionSavingText;
                    if (string.IsNullOrWhiteSpace(definitionText))
                    {
                        throw new Exception("Invalid format in indicator definition. Rectify the error before proceeding");
                    }
                    else indicatorDefinitions.Add(definitionText);
                }
                return indicatorDefinitions;
            }
        }

        public string MergingName
        {
            get
            {
                return txtMergingName.Text;
            }
        }

        public string MergingDescription
        {
            get
            {
                return txtMergingDescription.Text;
            }
        }

        private void btnAddNumber_Click(object sender, RoutedEventArgs e)
        {
            var indicatorDefinition = gridIndicatorDefinitions.SelectedItem as IndicatorDefinition;
            if (indicatorDefinition != null)
            {
                int value;
                bool converted = int.TryParse(txtNumber.Text, out value);
                if (!converted)
                {
                    MessageBox.Show("Please provide a number");
                    txtNumber.SelectAll();
                    txtNumber.Focus();
                    return;
                }

                var component = new DefinitionComponent
                {
                    Name = string.Format("[{0}]", value),
                    Tag = value
                };
                indicatorDefinition.AddComponent(component);
            }   
        }

        private void btnRemoveNumber_Click(object sender, RoutedEventArgs e)
        {
            var indicatorDefinition = gridIndicatorDefinitions.SelectedItem as IndicatorDefinition;
            if (indicatorDefinition != null)
            {
                if (string.IsNullOrWhiteSpace(indicatorDefinition.Definition)) ;
                else indicatorDefinition.RemoveComponent(); 
            }
        }
    }
}
